home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / gfx / misc / pchglib12.lha / SetUserCopList.c < prev    next >
C/C++ Source or Header  |  1992-11-15  |  7KB  |  183 lines

  1. #include <proto/exec.h>
  2. #include <proto/graphics.h>
  3. #include <exec/types.h>
  4. #include <exec/memory.h>
  5. #include <hardware/custom.h>
  6. #include <graphics/gfxmacros.h>
  7. #include <graphics/copper.h>
  8. #include <intuition/screens.h>
  9. #include <iff/pchg.h>
  10. #include <clib/pchglib_protos.h>
  11.  
  12. #if INCLUDE_VERSION<36
  13. FAILURE!! Amiga includes version<36
  14. #endif
  15.  
  16. /* This number is hardware dependent, and limits the numbers of colors
  17. changes written by PCHG_SetUserCopList(). */
  18.  
  19. #define MAX_PER_LINE_CHANGES (15)
  20.  
  21. extern struct Custom __far custom;
  22.  
  23.  
  24. /****** pchg.lib/PCHG_SetUserCopList ****************************************
  25.  
  26.    NAME
  27.        PCHG_SetUserCopList -- Set a ViewPort Copperlist using a PCHG chunk
  28.  
  29.    SYNOPSIS
  30.        PCHG_SetUserCopList(Offset, Length, ViewPort, PCHG, LineMask, LineData);
  31.  
  32.        VOID PCHG_SetUserCopList(WORD, UWORD, struct ViewPort *,
  33.                                      struct PCHGHeader *, APTR, APTR);
  34.  
  35.    FUNCTION
  36.        Creates the Copperlist defined by a PCHG header and data. If a user
  37.        Copperlist is already defined on the ViewPort, it is first
  38.        deallocated. If Length is 0, every change specified by the PCHG
  39.        chunk will be generated. If Length is not 0, every change which
  40.        happens on a line in the range Offset<->Offset+Length will be
  41.        generated.  In each case, an offset equal to Offset is subtracted
  42.        from the PCHG indications. For instance, if Offset == 8, Length ==
  43.        10, the changes specified in the PCHG chunk for the line range 8-17
  44.        will happen on the line range 0-9. This allows setting a Copperlist
  45.        for a scrolled picture (i.e., the first displayed line is not the
  46.        first picture line). If Offset == 0, Length == ViewPort->DHeight, only
  47.        the changes which happen inside the ViewPort will be generated (with
  48.        no offset). Do NOT ask for odd offsets for a laced picture, because
  49.        of the well-known limitations of MrgCop(). Note that when Offset is
  50.        non-zero, this function will stuff via SetRGB4() all the changes which
  51.        happens before the Offset line, so that the image will be correctly
  52.        displayed. This however implies you have to reload the CMAP before each
  53.        call with an offset.
  54.  
  55.    INPUTS
  56.        Offset       - A positive offset which will be subtracted from the
  57.                       line specified by the PCHG->StartLine field.
  58.        Length       - A number of lines which will limit the
  59.                       Copperlist generation. Ignored if == 0.
  60.        ViewPort     - The ViewPort which will receive the Copperlist.
  61.        PCHG         - The PCHGHeader.
  62.        LineMask     - The line mask pointer. Technically, the LINEMASK
  63.                       part of the PCHG grammar.
  64.        LineData     - The (Small|Big)PaletteChange array
  65.                       pointer. Technically, the second part of the LINEDATA
  66.                       part of the PCHG grammar.
  67.  
  68.    RESULT
  69.        None.
  70.  
  71.    EXAMPLE
  72.  
  73.    NOTES
  74.        The MAX_PER_LINE_CHANGES #define at the start of the source
  75.        code limits the maximum number of changes allowed on a
  76.        single line. No check is done for changes on odd lines if
  77.        the ViewPort is laced. MaxReg and MinReg are ignored.
  78.        This function does *not* call RethinkDisplay() for you,
  79.        and needs graphics.library. Remember to free the user Copperlist
  80.        (if you're using a &Screen->Viewport, Intuition will do it for you).
  81.  
  82.    BUGS
  83.        Background Copperlists which a PCHGHeader->StartLine
  84.        negative value will not be correctly displayed if Offset
  85.        is not 0, because only changes on a line >=Offset will be
  86.        generated. This shouldn't be a problem however.
  87.  
  88.    SEE ALSO
  89.  
  90. *****************************************************************************/
  91.  
  92. VOID PCHG_SetUserCopList(WORD Offset, UWORD Length, struct ViewPort *ViewPort, struct PCHGHeader *PCHG, APTR LineMask, APTR LineData) {
  93.  
  94.     LONG i,j,RegNum;
  95.     struct UCopList *UCop;
  96.     struct SmallLineChanges *slc;
  97.     UWORD *RGB, *PreRGB;
  98.     struct BigLineChanges *blc;
  99.     struct BigPaletteChange *bpl;
  100.     ULONG *Mask;
  101.     BOOL Change;
  102.  
  103.     Forbid();
  104.     if (ViewPort->UCopIns) {
  105.         if (ViewPort->UCopIns->FirstCopList) FreeCopList(ViewPort->UCopIns->FirstCopList);
  106.         FreeMem(ViewPort->UCopIns, sizeof(struct UCopList));
  107.         ViewPort->UCopIns = NULL;
  108.     }
  109.     Permit();
  110.  
  111.     Mask = LineMask;
  112.     blc = (void *)(slc = LineData);
  113.  
  114.     if ((UCop = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) return;
  115.  
  116.     CINIT(UCop, PCHG->TotalChanges+PCHG->ChangedLines);
  117.  
  118.     if (Length && (PreRGB = AllocMem(sizeof(UWORD)*(PCHG->MaxReg-PCHG->MinReg+1), MEMF_PUBLIC | MEMF_CLEAR)) != NULL) {
  119.         for(i=0; i<Offset-PCHG->StartLine; i++) {
  120.             if (Mask[i/32] & 1UL<<(31-(i%32))) {
  121.                 if (PCHG->Flags & PCHGF_12BIT) {
  122.                     RGB = (UWORD *)&slc[1];
  123.                     for(j=0; j<slc->ChangeCount16; j++) {
  124.                         RegNum = (*RGB>>12)&0xF;
  125.                         if (RegNum >= PCHG->MinReg && RegNum <= PCHG->MaxReg) PreRGB[RegNum-PCHG->MinReg] = 0x1000 | (*RGB & 0xFFF);
  126.                         RGB++;
  127.                     }
  128.                     for(j=0; j<slc->ChangeCount32; j++) {
  129.                         RegNum = ((*RGB>>12)&0xF)+16;
  130.                         if (RegNum >= PCHG->MinReg && RegNum <= PCHG->MaxReg) PreRGB[RegNum-PCHG->MinReg] = 0x1000 | (*RGB & 0xFFF);
  131.                         RGB++;
  132.                     }
  133.                     slc = (void *)RGB;
  134.                 }
  135.                 else if (PCHG->Flags & PCHGF_32BIT) {
  136.                     bpl = (void *)&blc[1];
  137.                     for(j=0; j<blc->ChangeCount; j++) {
  138.                         if (bpl->Register >= PCHG->MinReg && bpl->Register <= PCHG->MaxReg) PreRGB[bpl->Register-PCHG->MinReg] = 0x1000 | ((bpl->Red+8)&0xF0)<<4 | (bpl->Green+8)&0xF0 | ((bpl->Blue+8)>>4)&0xF;
  139.                         bpl++;
  140.                     }
  141.                     blc = (void *)bpl;
  142.                 }
  143.             }
  144.         }
  145.         for(i=0; i<=PCHG->MaxReg-PCHG->MinReg; i++) if (PreRGB[i] & 0x1000) SetRGB4(ViewPort, i+PCHG->MinReg, (PreRGB[i]>>8)&0xF, (PreRGB[i]>>4)&0xF, (PreRGB[i])&0xF);
  146.         FreeMem(PreRGB, sizeof(UWORD)*(PCHG->MaxReg-PCHG->MinReg+1));
  147.     }
  148.  
  149.     blc = (void *)(slc = LineData);
  150.  
  151.     for(i=0; i<PCHG->LineCount; i++) {
  152.         if (Mask[i/32] & 1UL<<(31-(i%32))) {
  153.             Change = (!Length || (i+PCHG->StartLine >= Offset && i+PCHG->StartLine < Offset+Length));
  154.             if (Change) CWAIT(UCop, i+PCHG->StartLine-Offset, 0);
  155.             if (PCHG->Flags & PCHGF_12BIT) {
  156.                 RGB = (UWORD *)&slc[1];
  157.                 for(j=0; j<slc->ChangeCount16; j++) {
  158.                     if (j<MAX_PER_LINE_CHANGES && Change) CMOVE(UCop, custom.color[(*RGB>>12)&0xF], *RGB & 0xFFF);
  159.                     RGB++;
  160.                 }
  161.                 for(j=0; j<slc->ChangeCount32; j++) {
  162.                     if (j+slc->ChangeCount16<MAX_PER_LINE_CHANGES && Change) CMOVE(UCop, custom.color[((*RGB>>12)&0xF)+16], *RGB & 0xFFF);
  163.                     RGB++;
  164.                 }
  165.                 slc = (void *)RGB;
  166.             }
  167.             else if (PCHG->Flags & PCHGF_32BIT) {
  168.                 bpl = (void *)&blc[1];
  169.                 for(j=0; j<blc->ChangeCount; j++) {
  170.                     if (j<MAX_PER_LINE_CHANGES && Change) CMOVE(UCop, custom.color[bpl->Register], (bpl->Red & 0xF0)<<4 | (bpl->Green & 0xF0) | bpl->Blue>>4);
  171.                     bpl++;
  172.                 }
  173.                 blc = (void *)bpl;
  174.             }
  175.         }
  176.     }
  177.  
  178.     CEND(UCop);
  179.     Forbid();
  180.     ViewPort->UCopIns = UCop;
  181.     Permit();
  182. }
  183.